package cn.itsource.service.impl;

import cn.itsource.doc.CourseDoc;
import cn.itsource.dto.CourseQueryDto;
import cn.itsource.mapper.HighlightResultMapper;
import cn.itsource.repo.CourseElasticsearchRepository;
import cn.itsource.result.JSONResult;
import cn.itsource.result.PageList;
import cn.itsource.service.EsService;
import cn.itsource.vo.AggTermsVo;
import io.netty.util.internal.StringUtil;
import org.apache.commons.lang.StringUtils;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.aggregations.Aggregation;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.bucket.terms.StringTerms;
import org.elasticsearch.search.aggregations.bucket.terms.Terms;
import org.elasticsearch.search.aggregations.bucket.terms.TermsAggregationBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.sort.FieldSortBuilder;
import org.elasticsearch.search.sort.ScoreSortBuilder;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.data.elasticsearch.core.aggregation.AggregatedPage;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.stereotype.Service;

import javax.swing.*;
import java.lang.management.BufferPoolMXBean;
import java.util.*;

/**
 * @Author: Jason
 * @Date: 2022/9/5 19:55
 */
@Service
public class EsServiceImpl implements EsService {

    @Autowired
    private CourseElasticsearchRepository repo;

    @Autowired
    private ElasticsearchTemplate elasticsearchTemplate;

    @Autowired
    private HighlightResultMapper highlightResultMapper;

    //最终版
    //课程搜索
    @Override
    public JSONResult searchCourse(CourseQueryDto dto) {
        //新建本地查询构建器
        NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();

        //分页
        queryBuilder.withPageable(PageRequest.of(dto.getPage() - 1, dto.getRows()));

        //排序
        SortOrder orderType = SortOrder.DESC;
        if(!"desc".equals(dto.getSortType())){
            orderType = SortOrder.ASC;
        }
        if(!StringUtils.isEmpty(dto.getSortField())){
            queryBuilder.withSort(new FieldSortBuilder(dto.getSortField()).order(orderType));
        }

        //组合查询器封装所有的条件（查询+过滤）
        BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder();

        //过滤
        if(dto.getCourseTypeId() != null){
            boolQueryBuilder.filter(QueryBuilders.termQuery("courseTypeId", dto.getCourseTypeId()));
        }
        if(dto.getPriceMin() != null){
            boolQueryBuilder.filter(QueryBuilders.rangeQuery("price")
                    .gte(dto.getPriceMin()));
        }
        if(dto.getPriceMax() != null){
            boolQueryBuilder.filter(QueryBuilders.rangeQuery("price")
                    .lte(dto.getPriceMax()));
        }
        if(!StringUtils.isEmpty(dto.getGradeName())){
            boolQueryBuilder.filter(QueryBuilders.termQuery("gradeName", dto.getGradeName()));
        }
        if(!StringUtils.isEmpty(dto.getTenantName())){
            boolQueryBuilder.filter(QueryBuilders.termQuery("tenantName", dto.getTenantName()));
        }


        //查询
        if(!StringUtils.isEmpty(dto.getKeyword())){
            boolQueryBuilder.must(QueryBuilders.multiMatchQuery(dto.getKeyword(), "name", "tenantName"));
            //boolQueryBuilder.must(QueryBuilders.matchQuery("tenantName", dto.getKeyword()));
            //boolQueryBuilder.must(QueryBuilders.matchQuery("tenantName", dto.getKeyword()));
        }

        queryBuilder.withQuery(boolQueryBuilder);

        //关键字高亮
        HighlightBuilder.Field field1 = new HighlightBuilder.Field("name").preTags("<font style='color:red'><b>").postTags("</b></font>");
        HighlightBuilder.Field field2 = new HighlightBuilder.Field("tenantName").preTags("<font style='color:red'><b>").postTags("</b></font>");

        queryBuilder.withHighlightFields(field1, field2);

        //聚合查询
        TermsAggregationBuilder termsAggregationBuilder1 = AggregationBuilders.terms("gradeAggs").field("gradeName").order(Terms.Order.count(false)).size(10);
        TermsAggregationBuilder termsAggregationBuilder2 = AggregationBuilders.terms("tenantAggs").field("tenantName").order(Terms.Order.count(false)).size(10);
        queryBuilder.addAggregation(termsAggregationBuilder1).addAggregation(termsAggregationBuilder2);

        //执行查询
        AggregatedPage<CourseDoc> page = elasticsearchTemplate.queryForPage(
                queryBuilder.build(), CourseDoc.class, highlightResultMapper);

        Map<String, List<AggTermsVo>> aggrMap = new HashMap<>();

        Map<String, Aggregation> stringAggregationMap = page.getAggregations().asMap();
        Set<Map.Entry<String, Aggregation>> entries = stringAggregationMap.entrySet();
        entries.forEach(e -> {
            List<AggTermsVo> list = new ArrayList<>();
            String key = e.getKey();
            StringTerms value = (StringTerms) e.getValue();
            //取出聚合计算结果
            List<StringTerms.Bucket> buckets = value.getBuckets();
            AggTermsVo dto2 = null;
            for(int i = 0; i<buckets.size(); i++){
                dto2 = new AggTermsVo();
                StringTerms.Bucket bucket = buckets.get(i);
                String keyAsString = bucket.getKeyAsString();
                long docCount = bucket.getDocCount();

                dto2.setKey(keyAsString);
                dto2.setDocCount(docCount);
                list.add(dto2);
            }
            aggrMap.put(key, list);
        });

        //返回结果集
        return JSONResult.success(new PageList<>(page.getTotalElements(), page.getContent(), aggrMap));
    }

//    //高亮版本
//    //课程搜索
//    public JSONResult searchCourse3(CourseQueryDto dto) {
//        //新建本地查询构建器
//        NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();
//
//        //分页
//        queryBuilder.withPageable(PageRequest.of(dto.getPage() - 1, dto.getRows()));
//
//        //排序
//        SortOrder orderType = SortOrder.DESC;
//        if(!"desc".equals(dto.getSortType())){
//            orderType = SortOrder.ASC;
//        }
//        if(!StringUtils.isEmpty(dto.getSortField())){
//            queryBuilder.withSort(new FieldSortBuilder(dto.getSortField()).order(orderType));
//        }
//
//        //组合查询器封装所有的条件（查询+过滤）
//        BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder();
//
//        //过滤
//        if(dto.getCourseTypeId() != null){
//            boolQueryBuilder.filter(QueryBuilders.termQuery("courseTypeId", dto.getCourseTypeId()));
//        }
//        if(dto.getPriceMin() != null){
//            boolQueryBuilder.filter(QueryBuilders.rangeQuery("price")
//                    .gte(dto.getPriceMin()));
//        }
//        if(dto.getPriceMax() != null){
//            boolQueryBuilder.filter(QueryBuilders.rangeQuery("price")
//                    .lte(dto.getPriceMax()));
//        }
//
//
//        //查询
//        if(!StringUtils.isEmpty(dto.getKeyword())){
//            boolQueryBuilder.must(QueryBuilders.multiMatchQuery(dto.getKeyword(), "name", "tenantName"));
//        }
//
//        queryBuilder.withQuery(boolQueryBuilder);
//
//        //关键字高亮
//        HighlightBuilder.Field field1 = new HighlightBuilder.Field("name").preTags("<font style='color:red'><b>").postTags("</b></font>");
//        HighlightBuilder.Field field2 = new HighlightBuilder.Field("tenantName").preTags("<font style='color:red'><b>").postTags("</b></font>");
//
//        queryBuilder.withHighlightFields(field1, field2);
//
//        //执行查询
//        Page<CourseDoc> result = elasticsearchTemplate.queryForPage(
//                queryBuilder.build(), CourseDoc.class, highlightResultMapper);
//
//        //返回结果集
//        return JSONResult.success(new PageList<>(result.getTotalElements(), result.getContent()));
//    }

//
//    //初版：仅仅做了查询过滤、分页排序等操作，没有做高亮和聚合查询
//    //课程搜索
//    public JSONResult searchCourse2(CourseQueryDto dto) {
//        //新建本地查询构建器
//        NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();
//
//        //分页
//        queryBuilder.withPageable(PageRequest.of(dto.getPage() - 1, dto.getRows()));
//
//        //排序
//        SortOrder orderType = SortOrder.DESC;
//        if(!"desc".equals(dto.getSortType())){
//            orderType = SortOrder.ASC;
//        }
//        if(!StringUtils.isEmpty(dto.getSortField())){
//            queryBuilder.withSort(new FieldSortBuilder(dto.getSortField()).order(orderType));
//        }
//
//        //组合查询器封装所有的条件（查询+过滤）
//        BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder();
//
//        //过滤
//        if(dto.getCourseTypeId() != null){
//            boolQueryBuilder.filter(QueryBuilders.termQuery("courseTypeId", dto.getCourseTypeId()));
//        }
//        if(dto.getPriceMin() != null){
//            boolQueryBuilder.filter(QueryBuilders.rangeQuery("price")
//                    .gte(dto.getPriceMin()));
//        }
//        if(dto.getPriceMax() != null){
//            boolQueryBuilder.filter(QueryBuilders.rangeQuery("price")
//                    .lte(dto.getPriceMax()));
//        }
//
//
//        //查询
//        if(!StringUtils.isEmpty(dto.getKeyword())){
//            boolQueryBuilder.must(QueryBuilders.matchQuery("name", dto.getKeyword()));
//        }
//
//        queryBuilder.withQuery(boolQueryBuilder);
//        //去仓库中执行查询操作
//        Page<CourseDoc> result = repo.search(queryBuilder.build());
//
//        //返回结果集
//        return JSONResult.success(new PageList<>(result.getTotalElements(), result.getContent()));
//    }
}
